package net.mygwt.ui.client.widget.treetable;

import java.util.ArrayList;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.WidgetHelper;

import net.mygwt.ui.client.Events;
import net.mygwt.ui.client.MyDOM;
import net.mygwt.ui.client.Style;
import net.mygwt.ui.client.data.Model;
import net.mygwt.ui.client.event.BaseEvent;
import net.mygwt.ui.client.event.Listener;
import net.mygwt.ui.client.viewer.TreeTableViewer;
import net.mygwt.ui.client.widget.table.HasValue;
import net.mygwt.ui.client.widget.tree.TreeItem;

/*
Rough guide to use:
-- use this inside a viewer (much like the TreeTableViewer, only you set up the editors to allow edits.
-- this is why the method setToggleOnDoubleClick has been added to Tree.java (so you can edit on double click)

--set up cols
TreeTableColumn[] columns = new TreeTableColumn[headerCount];
--one for each
TreeTableColumn ttc= new TreeTableColumn(colId, headerTxt, 1.0f * width);
--set them
TreeTableColumnModel cm = new TreeTableColumnModel(columns);
	    
--you can now create the tree
EditTreeTable table= new EditTreeTable(Style.SINGLE, cm);

--set up editors (on columns you want one on)
table.setEditor(i, ed);

--set the viewer and model
viewer = new TreeTableViewer(table);
viewer.setContentProvider(new ModelTreeContentProvider());
viewer.setInput(model);

--set up each cell label provider (1 per col)
TreeTableViewerColumn col = viewer.getViewerColumn(i);
CellLabelProvider clp= setupCellLabelProvider(i, col);
col.setLabelProvider(clp);

*/

public class EditTreeTable extends TreeTable {
  public static int ItemEdited= 15001;
  
  private boolean editmode= false;
  private TreeTableItem editItem= null;
  private ArrayList editors= new ArrayList();

  public EditTreeTable() {
    super();
    setupListener();
  }

  public EditTreeTable(TreeTableColumnModel cm) {
    super(cm);
    setupListener();
  }

  public EditTreeTable(int style, TreeTableColumnModel cm) {
    super(style, cm);
    setupListener();
    //TODO : stop double click expand, leave to edit
  }

  protected void setupListener() {
    setToggleOnDoubleClick(false);
    this.addListener(Events.RowDoubleClick, new Listener() {
      public void handleEvent(BaseEvent be) {
        System.err.println("Double Clicked - go into edit");
        onEdit((TreeTableItem) be.item);
      }
    });
  }
  
  public void onEdit(TreeTableItem item) {
    setEditModeOn(item);
    //setup editors:
    for(int i=0; i < editItem.getTreeTable().getColumnCount(); i++) {
      Widget editor= getEditor(i);
      if(editor != null) {
        Object editItemValue= editItem.getValue(i);
        if(editItemValue != null) {
          System.err.println("editItemValue = " + editItemValue);
          if(editor instanceof HasValue) {
            ((HasValue)editor).setValue(editItemValue);
          } else if(editor instanceof HasText) {
            if(editItemValue == null) {
              ((HasText)editor).setText("");
            } else {
              ((HasText)editor).setText(editItemValue.toString());
            }
          }
        }
        Element edElement= editor.getElement();
//      MyDOM.setStyleName(edElement, "my-tbl-col-edit-text");
      int w = getColumnModel().getWidthInPixels(i) - 10;
      MyDOM.setStyleAttribute(edElement, "width", w+"px");
//      called in setValue ... WidgetHelper.doAttach(editor);
        setData("preedit:"+i, editItemValue);
        editItem.setValue(i, editor);
      }
    }
  }

  protected void setEditModeOn(TreeTableItem item) {
    editmode= true;
    editItem= item;
    editItem.setTreeTable(this);
    disableTextSelection(false);
    item.disableTextSelection(false);
  }
  
  protected void setEditModeOff() {
    editItem.disableTextSelection(true);
    disableTextSelection(true);
    editmode= false;
    editItem= null;
  }

  public Widget getEditor(int col) {
    try {
      return (Widget) editors.get(col);
    } catch(Exception e) {
      return null;
    }
  }

  public void setEditor(int col, Widget widget) {
    if(col < editors.size()) {
      //replace existing
      editors.set(col, widget);
    } else {
      editors.add(col, widget);
    }
  }

  public void onBrowserEvent(Event event) {
    //only if not in edit mode
    if(!editmode) { 
      super.onBrowserEvent(event);
    } else {
      int evtType= DOM.eventGetType(event);
      if(evtType == Event.ONKEYDOWN) {
        int keyCode = DOM.eventGetKeyCode(event);
        if (keyCode == KeyboardListener.KEY_ESCAPE) {
          cancelEdit();
        } else if(keyCode == KeyboardListener.KEY_ENTER) {
          commitEdit();
        }
      } else if(evtType == Event.ONCLICK || evtType == Event.ONDBLCLICK) {
        TreeItem item = findItem(DOM.eventGetTarget(event));
        if(item != editItem) {
          commitEdit();
        }
//        else {
//          System.err.println("ignore click");
//        }
      } 
    }
  }
  
  protected void commitEdit() {
    System.err.println("commit edit");
    if(editItem != null) {
      for(int i=0; i < editItem.getTreeTable().getColumnCount(); i++) {
        Widget editor= getEditor(i);
        if(editor != null) {
          if(editor instanceof HasValue) {
            Object o = ((HasValue)editor).getValue();
            Object preVal= getData("preedit:"+i);
            if((o == null && preVal == null) || (o != null && o.equals(preVal))) {
              editItem.setValue(i, preVal);
            } else {
              editItem.setValue(i, o);
              BaseEvent be= new BaseEvent();
              be.value= ((HasValue)editor).getValue();
              be.item= editItem;
              be.index= i;

              fireEvent(ItemEdited, be);
            }
          } else if(editor instanceof HasText) {
            String val= ((HasText)editor).getText();
            Object preVal= getData("preedit:"+i);
            if((val == null && preVal == null) || (val != null && val.equals(preVal))) {
              editItem.setValue(i, preVal);
            } else {
              editItem.setText(i, val);
              BaseEvent be= new BaseEvent();
              be.value= val;
              be.item= editItem;
              be.index= i;

              fireEvent(ItemEdited, be);
            }
          }
          WidgetHelper.doDetach(editor);
        }
      }
      setEditModeOff();
    }
  }
  
  protected void cancelEdit() {
    System.err.println("cancel edit");
    for(int i=0; i < editItem.getTreeTable().getColumnCount(); i++) {
      Object preVal= getData("preedit:"+i);
      Widget editor= getEditor(i);
      editItem.setValue(i, preVal);
      if(editor != null) {
//      if(editor instanceof HasValue) {
//      editItem.setValue(i, ((HasValue)editor).getValue());
//      } else if(editor instanceof HasText) {
//      String val= ((HasText)editor).getText();
//      editItem.setText(i, val);
//      }
        WidgetHelper.doDetach(editor);
      }
    }
    setEditModeOff();
  }
  
  public void hideColumn(int colIndex) {
    getHeader().showColumn(colIndex, false);
  }
  
  public void finishEdits() {
    commitEdit();
  }
  
}